import { AfterViewInit, Component, ComponentRef, OnDestroy, OnInit } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd';
import { compareDataField, getDataBindFieldValue } from 'src/app/common/tools/condition-tool';
import { BaseService, DataRegisterService } from 'src/app/services';
import { DepartmentService } from 'src/app/services/department.service';
import { EventManagerService } from 'src/app/services/event-manager.service';
import { OrganizationService } from 'src/app/services/organization.service';
import { UploadService } from 'src/app/services/upload.service';
import { PermitConfig, PermitConfigId } from '../../../models';
import { EngineService } from '../../../services/engine.service';
import { BaseFieldComponent } from '../base-field/base-field.component';
import { WorkflowPageService } from 'src/app/common/page-render/workflow-page-container/workflow-page.service';

@Component({
  selector: 'zepride-select',
  templateUrl: './select.component.html',
  styleUrls: ['../field.common.less', './select.component.less']
})
export class SelectComponent extends BaseFieldComponent implements OnInit, AfterViewInit, OnDestroy {

  dataSource: any[] = [];
  selectMode: 'default' | 'multiple' = 'default';
  value: any = [];
  permitConfig: PermitConfig[] = [
    { mode: 'query', permitId: '查看', permitName: '', authObjectId: '' },
    { mode: 'edit', permitId: '编辑', permitName: '', authObjectId: '' }
  ];
  disabled = false;
  refComs: ComponentRef<BaseFieldComponent>[] = [];
  sourceDs;
  isChildFlow = false;

  readonlyValue;

  constructor(
    protected engineService: EngineService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    protected orgSvr: OrganizationService,
    public uploadService: UploadService,
    protected msg: NzMessageService,
    public departmentSvr: DepartmentService,
    private workflowPageService: WorkflowPageService,
    protected dataRegisterService: DataRegisterService
  ) {
    super(engineService, baseSvr, eventSvr, orgSvr, uploadService, msg, dataRegisterService);
  }

  async ngOnInit() {
    if (!this.componentData.defaultValue) {
      this.componentData.defaultValue = [];
    }

    const selectType = this.componentData.extends.selectType;
    this.selectMode = selectType == 'single' ? 'default' : 'multiple';

    if (this.componentData.dataSource) {
      if (this.componentData.dataSource.type === 'innerDs') {
        await this.getDataSourceData(this.componentData.dataSource.dataSourceId);
        if (this.componentData.dataSource.innerDsDefaultValue && (!this.componentData.defaultValue || this.componentData.defaultValue.length == 0)) {
          const value = this.bindData ? this.bindData : this.componentData.dataSource.innerDsDefaultValue;
          this.setBindData(value);
        }
      } else if (this.componentData.dataSource.type === 'autoDs') {
        this.dataSource = this.componentData.dataSource.ds;
        this.dataSource = this.dataSource.filter(x => x.key);
      } else if (this.componentData.dataSource.type === 'outsideDs') {
        const url = this.componentData.dataSource.url;
        const data = getDataBindFieldValue(this.engineService.currentDataModel, url);
        let result = [];
        if (data && data.length) {
          const fields = url.split('.');
          const valueField = fields[fields.length - 1];
          result = data.map(item => {
            const key = valueField;
            const value = item[key];
            return { key, value };
          });
        }
        this.dataSource = result;
      }

      this.setNewValue();
    }

    this.filterDs();
    this.readonlyValue = this.getReadonlyValue();
  }

  private setNewValue() {
    const selectType = this.componentData.extends.selectType;
    if (this.bindData) {
      if (selectType == 'single') {
        if (typeof (this.bindData) == 'string') {
          this.value = this.bindData as any;
        } else {
          const item = this.dataSource.find(x => x.value.id == this.bindData.id || x.value == this.bindData);
          if (item) {
            this.value = item.value;
          }
        }
      } else if (selectType == 'multi') {

        if (!Array.isArray(this.bindData)) {
          this.setData([this.bindData]);
        }

        this.value = this.dataSource.filter(x => {
          if (x.value.id) {
            return this.bindData.find(n => n.id == x.value.id);
          } else {
            return this.bindData.find(n => n == x.value);
          }
        }).map(x => x.value);
      }
    }
  }

  getReadonlyValue() {
    if (Array.isArray(this.value)) {
      if (this.value.length == 0 && this.bindData) {
        return this.bindData.nodeName;
      }
      return this.value.join(',');
    }
    else {
      if (typeof (this.value) == 'object' && this.value) {
        if ((this.value as any).object) {
          // 表示是内部数据源，组织机构，人员，部门等
          return this.value.nodeName;
        } else {
          return this.value[this.componentData.dataSource.bindField];
        }
      }
      return this.value;
    }
  }

  ngAfterViewInit() {
    setTimeout(() => {
      const authData = this.setAuthorityData();
      this.zeprideAuthorityData = {
        ...authData,
        afterChecked: this.afterAuthChecked.bind(this)
      };
    });
    this.registerModelChange();
  }

  registerModelChange() {
    // .pipe(
    //   debounceTime(200)
    // )
    this.modelChange$ = this.engineService.dataModelChange$.subscribe(data => {
      if (data.identifyId !== this.componentData.identifyId) {
        this.filterDs();
        this.readonlyValue = this.getReadonlyValue();
        // 表示是关联组件数据值的绑定方式
        let t = [];
        if (this.componentData.dataSource && this.componentData.dataSource.url) {
          t = this.componentData.dataSource.url.split('.');
        }
        if (t.length > 1) {
          if (data.bindField !== t[0]) {
            return;
          }

          let keyName = 'nodeName';
          if (t[2]) {
            keyName = t[2];
          }

          if (data.value && data.value[t[1]]) {
            this.dataSource = data.value[t[1]].map(x => {
              return {
                key: x[keyName],
                value: x
              };
            });

            if (this.dataSource[0]) {
              this.value = this.dataSource[0].value;
            } else {
              this.value = null;
            }
          }
          else {
            this.dataSource = [];
            this.clearValueIfDataSourceNull();
          }

          if (this.dataSource && this.dataSource.length > 0) {
            this.value = this.dataSource[0].value;
            this.setBindData(this.dataSource[0].value);
          }
          else {
            this.clearValueIfDataSourceNull();
          }
        }
        else {
          this.setNewValue();
          if (data.bindField !== this.componentData.bindField) {
            return;
          }
        }

        this.conditionHandle();
      }
    });
  }

  /**
   * 设置绑定字段的值
   * @param value 新的值
   */
  setBindData(value: any) {
    const bindField = this.componentData.bindField;
    if (bindField) {
      this.formatObj(value, bindField);
      this.setMapBindData(this.getReadonlyValue());
      this.engineService.dataModelChange$.next({
        bindField,
        value,
        identifyId: this.componentData.identifyId,
        tmpComItemId: this.tmpComItemId,
        dataModel: this.dataModel,
        selector: this.componentData.selector
      });
      this.componentData.defaultValue = value;
    } else {
      this.componentData.defaultValue = value;
    }
  }

  filterDs() {
    const queryKeyValue = [];
    if (!this.componentData.extends.refTmpComItemIds || !this.componentData.extends.refTmpComItemIds.length) {
      return;
    }
    if (this.refComs.length == 0) {
      this.refComs = this.engineService.componentRefs.filter(x => this.componentData.extends.refTmpComItemIds.find(n => n == x.instance.tmpComItemId));
    }

    this.refComs.map(x => {
      if (x.instance.componentData.selector == 'address-select') {
        const value: string = x.instance.bindData;
        if (!value) {
          return;
        }
        const t = value.split(',');
        // t = t.filter(n => n != '省本级' && n != '市本级');

        queryKeyValue.push({
          key: x.instance.componentData.bindField,
          value: t.join(',')
        });
      }
      else {
        queryKeyValue.push({
          key: x.instance.componentData.bindField,
          value: x.instance.bindData
        });
      }
    });
    if (!this.sourceDs || this.sourceDs.length == 0) {
      this.sourceDs = this.dataSource;
    }
    // 关联组件的数据过滤方法
    this.dataSource = this.sourceDs.filter(x => {
      if (x.value) {
        let flag = false;
        for (const item of queryKeyValue) {
          if (x.value[item.key] && x.value[item.key].indexOf(item.value) > -1) {
            flag = true;
          }
          else {
            flag = false;
          }
        }
        return flag;
      }
      return false;
    });

    // if (!this.value || this.value.length == 0) {
    // console.log('00000', this.componentData.bindField, this.dataSource.length)
    if (this.dataSource.length > 0) {
      let newValue;
      if (this.bindData) {
        const has = this.dataSource.find(x => x.id == this.bindData.id);
        if (has) {
          newValue = has.value;
        } else { newValue = this.dataSource[0].value; }
      } else {
        newValue = this.dataSource[0].value;
      }
      if (this.value != newValue) {
        this.value = newValue;
        this.setBindData(this.value);
      }
    } else {
      if (this.dataSource.length == 0 && this.value != null) {
        this.clearValueIfDataSourceNull();
      }
    }
  }

  private clearValueIfDataSourceNull() {
    for (const key in this.dataModel) {
      if (key.indexOf('.') > -1) {
        const keySplitList = key.split('.');
        if (keySplitList.find(x => x == this.componentData.bindField)) {
          this.dataModel[key] = null;
        }
      }
      else {
        if (key == this.componentData.bindField) {
          this.dataModel[key] = null;
        }
      }
    }

    this.value = null;
    this.setBindData(this.value);
  }

  async getDataSourceData(dsId: string) {
    const dataSourceData = await this.baseSvr.get('api/dataSource/' + dsId);
    if (dataSourceData.dataType.indexOf('keyValue') > -1) {
      this.dataSource = dataSourceData.data;
      this.dataSource.forEach(item => {
        item.key = item.value;
      });
    }
    else if (dataSourceData.dataType == 'department') {
      await this.getDepartmentDs();
    }
    else if (dataSourceData.dataType == 'user') {
      await this.getUserDs();
    }
    else if (dataSourceData.dataType == 'organization') {
      await this.getOrgDs();
    }
    else {
      const params = {
        dataType: dataSourceData.dataType,
        objectId: dataSourceData.objectId
      } as any;
      if (dataSourceData.objectType === 'childrenWorkflow' && this.workflowPageService.currentDataRegisterId) {
        this.isChildFlow = true;
        params.parentDataRegisterId = this.workflowPageService.currentDataRegisterId;
      }
      const datas = await this.baseSvr.get('api/data', { params });

      this.dataSource = datas.list.map(item => {
        return {
          key: item[this.componentData.dataSource.bindField],
          value: item
        };
      });
    }
  }

  private async getDepartmentDs() {
    const orgId = localStorage.getItem('orgid');
    const datas = await this.orgSvr.getOrganizationTrees({
      organizationId: orgId,
      objectName: 'Department'
    });

    const employeeList = await this.orgSvr.getOrganizationTrees({
      organizationId: orgId,
      objectName: 'User'
    });

    for (const item of datas) {
      item.employeeList = employeeList.filter(x => x.parentId == item.id);
    }

    this.dataSource = datas.map(x => {
      return {
        key: x.nodeName,
        value: x
      };
    });
  }

  private async getUserDs() {
    const orgId = localStorage.getItem('orgid');
    const datas = await this.orgSvr.getOrganizationTrees({
      organizationId: orgId,
      objectName: 'User'
    });

    this.dataSource = datas.map(x => {
      return {
        key: x.nodeName,
        value: x
      };
    });
  }

  private async getOrgDs() {
    const orgId = localStorage.getItem('orgid');
    const orgInfo = await this.orgSvr.getOrganizationInfoById(orgId);
    this.dataSource = [{
      key: orgInfo.name,
      value: orgInfo
    }];
  }

  private conditionHandle() {
    if (this.componentData.condition) {
      // 判断条件
      const result = compareDataField(this.dataModel, this.componentData.condition);
      this.componentData.condition.objectId = this.componentData.tmpComItemId;
      this.engineService.componentRenderChanged$.next({
        actionType: 'show',
        isShow: result,
        condition: this.componentData.condition,

      });
    }
  }

  afterAuthChecked(params: { permitId: PermitConfigId, isAuthorized: boolean }) {
    if (!params.isAuthorized && !this.disabled) {
      this.disabled = true;
    }
  }

  expandedValidation = () => {
    if (this.isChildFlow) {
      const errors = this.engineService.fieldErrors;
      if (!this.componentData.defaultValue || (Array.isArray(this.componentData.defaultValue) && !this.componentData.defaultValue.length)) {
        const fieldError = {
          errors: { required: true },
          expanded: true,
          inValid: true,
          identifyId: this.componentData.identifyId,
          name: this.componentData.labelText
        };
        if (errors && errors.length) {
          const index = errors.findIndex(err => err.identifyId === this.componentData.identifyId && err.expanded);
          if (index > -1) {
            errors[index] = fieldError;
          } else {
            errors.push(fieldError);
          }
        } else {
          this.engineService.fieldErrors = [fieldError];
        }
      } else {
        if (errors && errors.length) {
          const index = errors.findIndex(err => err.identifyId === this.componentData.identifyId && err.expanded);
          if (index > -1) {
            errors.splice(index, 1);
          }
        }
      }
    }
  }

  ngOnDestroy() {
    if (this.modelChange$) {
      this.modelChange$.unsubscribe();
    }
  }
  // pageSavedHandle = async () => {
  //   console.log(this.value, this.componentData.bindField);
  //   this.dataModel[this.componentData.bindField] = this.value;
  // }

  getChangeLogSource() {
    if (typeof (this.dataChangeLog.sourceValue) == 'object') {
      if (this.dataChangeLog.sourceValue.nodeName) {
        return this.dataChangeLog.sourceValue.nodeName;
      }
      if (Array.isArray(this.dataChangeLog.sourceValue)) {
        return this.dataChangeLog.sourceValue.join(',');
      }
    }
    else {
      return this.dataChangeLog.sourceValue;
    }
  }

  getChangeLogTarget() {
    if (typeof (this.dataChangeLog.targetValue) == 'object') {
      if (this.dataChangeLog.targetValue.nodeName) {
        return this.dataChangeLog.targetValue.nodeName;
      }
      if (Array.isArray(this.dataChangeLog.targetValue)) {
        return this.dataChangeLog.targetValue.join(',');
      }
    }
    else {
      return this.dataChangeLog.targetValue;
    }
  }

  pageSavedHandle = async () => {
    if (this.isChildFlow && this.componentData.defaultValue && this.componentData.defaultValue.id) {
      this.workflowPageService.currentChildDataRegisterId = this.componentData.defaultValue.id;
    }
  }
}
